package org.gdstash.ui.character;

import org.gdstash.character.GDChar;
import org.gdstash.db.*;
import org.gdstash.ui.GDHelpActionListener;
import org.gdstash.ui.GDStashFrame;
import org.gdstash.ui.util.AdjustablePanel;
import org.gdstash.util.GDImagePool;
import org.gdstash.util.GDMsgFormatter;

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class GDCharMasteryPane extends AdjustablePanel {
    private static MasteryInfo[] CLASS_INFOS;
    private GDChar gdc;
    private GDCharMasteryImagePane imgPane;
    private JComboBox<MasteryInfo> cbMastery;
    private JLabel lblSkillDesc;
    private JLabel lblSkillPoints;
    private JTextField ftSkillPoints;
    private JButton btnHelp;
    private GDUIMasterySupport masterySupport;
    private boolean selMastery;
    private String masteryID;

    public static void loadMasteries() {
        final List<DBEnginePlayerMasteries> masteryTrees = DBEnginePlayerMasteries.get();
        if (masteryTrees == null) {
            return;
        }
        final List<DBClassTable> cTabs = new LinkedList<DBClassTable>();
        for (final DBEnginePlayerMasteries mt : masteryTrees) {
            final DBSkillTree tree = DBSkillTree.get(mt.getSkillTreeID());
            if (tree == null) {
                continue;
            }
            final DBSkill skill = tree.getMasterySkill();
            if (skill == null) {
                continue;
            }
            final DBSkillButton button = DBSkillButton.getBySkillID(skill.getSkillID());
            if (button == null) {
                continue;
            }
            final DBClassTable ct = DBClassTable.getByMasteryID(button.getButtonID());
            if (ct == null) {
                continue;
            }
            cTabs.add(ct);
        }
        (GDCharMasteryPane.CLASS_INFOS = new MasteryInfo[cTabs.size() + 1])[0] = new MasteryInfo();
        GDCharMasteryPane.CLASS_INFOS[0].ct = null;
        GDCharMasteryPane.CLASS_INFOS[0].id = "";
        GDCharMasteryPane.CLASS_INFOS[0].name = "";
        int i = 1;
        for (final DBClassTable ct2 : cTabs) {
            GDCharMasteryPane.CLASS_INFOS[i] = new MasteryInfo();
            GDCharMasteryPane.CLASS_INFOS[i].ct = ct2;
            final DBSkillButton sb = DBSkillButton.getByButtonID(ct2.getMasteryID());
            if (sb == null) {
                GDCharMasteryPane.CLASS_INFOS[i].id = "";
                GDCharMasteryPane.CLASS_INFOS[i].name = "";
            } else {
                final DBSkill skill2 = DBSkill.get(sb.getSkillID());
                if (skill2 == null) {
                    GDCharMasteryPane.CLASS_INFOS[i].id = "";
                    GDCharMasteryPane.CLASS_INFOS[i].name = "";
                } else {
                    GDCharMasteryPane.CLASS_INFOS[i].id = skill2.getSkillID();
                    GDCharMasteryPane.CLASS_INFOS[i].name = ct2.getMasteryTitle(0);
                    if (GDCharMasteryPane.CLASS_INFOS[i].name == null) {
                        GDCharMasteryPane.CLASS_INFOS[i].name = skill2.getName();
                    }
                    if (GDCharMasteryPane.CLASS_INFOS[i].name == null) {
                        GDCharMasteryPane.CLASS_INFOS[i].name = GDCharMasteryPane.CLASS_INFOS[i].id;
                    }
                }
            }
            ++i;
        }
        sortMasteryInfo();
    }

    private static void setClassInfoByGender(final int genderCode) {
        for (int i = 0; i < GDCharMasteryPane.CLASS_INFOS.length; ++i) {
            if (GDCharMasteryPane.CLASS_INFOS[i].ct != null) {
                GDCharMasteryPane.CLASS_INFOS[i].name = GDCharMasteryPane.CLASS_INFOS[i].ct.getMasteryTitle(genderCode);
            }
        }
    }

    private static void sortMasteryInfo() {
        Arrays.sort(GDCharMasteryPane.CLASS_INFOS);
    }

    public GDCharMasteryPane(final GDUIMasterySupport masterySupport, final boolean selMastery) {
        this.masterySupport = masterySupport;
        this.selMastery = selMastery;
        this.imgPane = new GDCharMasteryImagePane(masterySupport, selMastery);
        this.adjustUI();
        final JPanel pnlPoints = this.buildSkillPointPanel();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final Border lowered = BorderFactory.createEtchedBorder(1);
        final Border raised = BorderFactory.createEtchedBorder(0);
        final Border compound = BorderFactory.createCompoundBorder(raised, lowered);
        layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(pnlPoints).addComponent(this.imgPane)).addGroup(layout.createParallelGroup().addComponent(this.lblSkillDesc));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(pnlPoints)).addGroup(layout.createParallelGroup().addComponent(this.imgPane).addComponent(this.lblSkillDesc));
        layout.setVerticalGroup(vGroup);
        layout.linkSize(1, this.imgPane, this.lblSkillDesc);
        this.addMouseListener(new MouseInfo());
        this.addMouseMotionListener(new MouseInfo());
    }

    @Override
    public void adjustUI() {
        Font fntLabel = UIManager.getDefaults().getFont("Label.font");
        Font fntButton = UIManager.getDefaults().getFont("Button.font");
        if (fntButton == null) {
            fntButton = fntLabel;
        }
        Font fntCombo = UIManager.getDefaults().getFont("ComboBox.font");
        if (fntCombo == null) {
            fntCombo = fntLabel;
        }
        Font fntFText = UIManager.getDefaults().getFont("FormattedTextField.font");
        if (fntFText == null) {
            fntFText = fntLabel;
        }
        fntLabel = fntLabel.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntButton = fntButton.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntCombo = fntCombo.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntFText = fntFText.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        if (this.cbMastery == null) {
            if (GDCharMasteryPane.CLASS_INFOS == null) {
                this.cbMastery = new JComboBox<MasteryInfo>();
            } else {
                this.cbMastery = new JComboBox<MasteryInfo>(GDCharMasteryPane.CLASS_INFOS);
            }
            this.cbMastery.setEnabled(this.selMastery);
            this.cbMastery.addActionListener(new MasteryListener());
        }
        this.cbMastery.setFont(fntCombo);
        if (this.lblSkillDesc == null) {
            (this.lblSkillDesc = new JLabel()).setVerticalTextPosition(1);
            this.lblSkillDesc.setHorizontalAlignment(0);
        }
        this.lblSkillDesc.setFont(fntLabel);
        if (this.lblSkillPoints == null) {
            this.lblSkillPoints = new JLabel();
        }
        this.lblSkillPoints.setText(GDMsgFormatter.getString(GDMsgFormatter.rbGD, "TXT_CHAR_POINTS_SKILL"));
        this.lblSkillPoints.setFont(fntLabel);
        if (this.ftSkillPoints == null) {
            (this.ftSkillPoints = new JFormattedTextField()).setEditable(false);
        }
        this.ftSkillPoints.setFont(fntFText);
        if (this.btnHelp == null) {
            (this.btnHelp = new JButton()).addActionListener(new GDHelpActionListener("08_masteryinfo.html"));
        }
        this.btnHelp.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_HELP"));
        this.btnHelp.setIcon(GDImagePool.iconBtnQuestion24);
        this.btnHelp.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnHelp, "MNC_HELP");
        if (this.imgPane != null) {
            this.imgPane.adjustUI();
        }
    }

    private JPanel buildSkillPointPanel() {
        final JPanel panel = new JPanel();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        if (this.selMastery) {
            hGroup.addGroup(layout.createParallelGroup().addComponent(this.cbMastery)).addGroup(layout.createParallelGroup().addComponent(this.lblSkillPoints)).addGroup(layout.createParallelGroup().addComponent(this.ftSkillPoints)).addGroup(layout.createParallelGroup().addComponent(this.btnHelp));
        } else {
            hGroup.addGroup(layout.createParallelGroup().addComponent(this.cbMastery)).addGroup(layout.createParallelGroup().addComponent(this.lblSkillPoints)).addGroup(layout.createParallelGroup().addComponent(this.ftSkillPoints));
        }
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        if (this.selMastery) {
            vGroup.addGroup(layout.createParallelGroup().addComponent(this.cbMastery).addComponent(this.lblSkillPoints).addComponent(this.ftSkillPoints).addComponent(this.btnHelp));
        } else {
            vGroup.addGroup(layout.createParallelGroup().addComponent(this.cbMastery).addComponent(this.lblSkillPoints).addComponent(this.ftSkillPoints));
        }
        layout.setVerticalGroup(vGroup);
        layout.linkSize(0, this.lblSkillPoints, this.cbMastery);
        layout.linkSize(0, this.lblSkillPoints, this.ftSkillPoints);
        if (this.selMastery) {
            layout.linkSize(0, this.lblSkillPoints, this.btnHelp);
        }
        layout.linkSize(1, this.lblSkillPoints, this.cbMastery);
        layout.linkSize(1, this.lblSkillPoints, this.ftSkillPoints);
        if (this.selMastery) {
            layout.linkSize(1, this.lblSkillPoints, this.btnHelp);
        }
        return panel;
    }

    public void updateConfig() {
        this.setSkillPoints(this.masterySupport.getSkillPoints());
        this.imgPane.updateConfig();
        if (this.selMastery) {
            final int p = this.imgPane.getPointsSpent();
            this.masterySupport.setSkillPoints(this.masterySupport.getSkillPoints() + p);
            this.imgPane.setMastery(null);
            if (this.cbMastery != null) {
                final DefaultComboBoxModel<MasteryInfo> model = new DefaultComboBoxModel<MasteryInfo>(GDCharMasteryPane.CLASS_INFOS);
                this.cbMastery.setModel(model);
                this.cbMastery.setSelectedIndex(0);
            }
        } else if (this.cbMastery != null) {
            final MasteryInfo info = (MasteryInfo) this.cbMastery.getSelectedItem();
            final DefaultComboBoxModel<MasteryInfo> model = new DefaultComboBoxModel<MasteryInfo>(GDCharMasteryPane.CLASS_INFOS);
            this.cbMastery.setModel(model);
            int index = 0;
            if (info != null) {
                for (int i = 0; i < GDCharMasteryPane.CLASS_INFOS.length; ++i) {
                    if (info.id.equals(GDCharMasteryPane.CLASS_INFOS[i].id)) {
                        index = i;
                        break;
                    }
                }
            }
            this.cbMastery.setSelectedIndex(index);
        }
    }

    public int getPointsForSkill(final String skillID) {
        if (this.imgPane == null) {
            return 0;
        }
        return this.imgPane.getPointsForSkill(skillID);
    }

    public void setChar(final GDChar gdc) {
        this.gdc = gdc;
        this.imgPane.setChar(gdc);
        this.setSkillPoints(this.masterySupport.getSkillPoints());
    }

    public void setSkillPoints(final int points) {
        this.ftSkillPoints.setText(Integer.toString(points));
    }

    public void updateChar(final GDChar gdc) {
        if (gdc == null) {
            return;
        }
        this.imgPane.updateChar(gdc);
    }

    public void setMastery(final String masteryID) {
        this.masteryID = masteryID;
        this.imgPane.setMastery(masteryID);
        if (GDCharMasteryPane.CLASS_INFOS == null) {
            return;
        }
        int index = 0;
        if (masteryID != null) {
            for (int i = 0; i < GDCharMasteryPane.CLASS_INFOS.length; ++i) {
                if (GDCharMasteryPane.CLASS_INFOS[i].id.equals(masteryID)) {
                    index = i;
                    break;
                }
            }
        }
        this.cbMastery.setSelectedIndex(index);
    }

    public void resetMastery(final String masteryID) {
        if (masteryID == null) {
            return;
        }
        if (!masteryID.equals(this.masteryID)) {
            return;
        }
        this.imgPane.setMastery(null);
    }

    public static class MasteryInfo implements Comparable<MasteryInfo> {
        public DBClassTable ct;
        public String id;
        public String name;

        @Override
        public String toString() {
            return this.name;
        }

        public String getID() {
            return this.id;
        }

        public String getMasteryTitle(final int genderCode) {
            return this.ct.getMasteryTitle(genderCode);
        }

        @Override
        public int compareTo(final MasteryInfo info) {
            if (info == null) {
                return -1;
            }
            return this.name.compareTo(info.name);
        }
    }

    private class MouseInfo extends MouseAdapter {
        @Override
        public void mouseMoved(final MouseEvent e) {
            final int x = e.getX();
            final int y = e.getY();
            final int cx = GDCharMasteryPane.this.imgPane.getX();
            final int cy = GDCharMasteryPane.this.imgPane.getY();
            final int cw = GDCharMasteryPane.this.imgPane.getWidth();
            final int ch = GDCharMasteryPane.this.imgPane.getHeight();
            if (cx <= x && cx + cw >= x && cy <= y && cy + ch >= y) {
                String s = GDCharMasteryPane.this.imgPane.getSkillDescription(x - cx, y - cy);
                if (s == null) {
                    s = "";
                }
                GDCharMasteryPane.this.lblSkillDesc.setText(s);
                GDCharMasteryPane.this.lblSkillDesc.setVerticalTextPosition(1);
            }
        }

        @Override
        public void mouseClicked(final MouseEvent e) {
            final int x = e.getX();
            final int y = e.getY();
            final int cx = GDCharMasteryPane.this.imgPane.getX();
            final int cy = GDCharMasteryPane.this.imgPane.getY();
            final int cw = GDCharMasteryPane.this.imgPane.getWidth();
            final int ch = GDCharMasteryPane.this.imgPane.getHeight();
            if (cx <= x && cx + cw >= x && cy <= y && cy + ch >= y) {
                String s = null;
                if (SwingUtilities.isLeftMouseButton(e)) {
                    s = GDCharMasteryPane.this.imgPane.incSkill(x - cx, y - cy);
                }
                if (SwingUtilities.isRightMouseButton(e)) {
                    s = GDCharMasteryPane.this.imgPane.decSkill(x - cx, y - cy);
                }
                if (s == null) {
                    s = "";
                }
                GDCharMasteryPane.this.lblSkillDesc.setText(s);
            }
        }
    }

    private class MasteryListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            final int i = GDCharMasteryPane.this.cbMastery.getSelectedIndex();
            if (GDCharMasteryPane.this.masteryID != null && !GDCharMasteryPane.CLASS_INFOS[i].id.equals(GDCharMasteryPane.this.masteryID)) {
                final int p = GDCharMasteryPane.this.imgPane.getPointsSpent();
                GDCharMasteryPane.this.masterySupport.setSkillPoints(GDCharMasteryPane.this.masterySupport.getSkillPoints() + p);
            }
            GDCharMasteryPane.this.setMastery(GDCharMasteryPane.CLASS_INFOS[i].id);
        }
    }
}
